package Jogo.Entities {
	import Jogo.Main;
	import Jogo.States.PhaseState;
	import Jogo.Util;
	
	import flash.display.Bitmap;
	import flash.display.FrameLabel;
	import flash.display.MovieClip;
	import flash.display.Stage;
	import flash.geom.Point;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.utils.getTimer;
	
	import mx.core.INavigatorContent;
	
	/** Describes the turrets used by the player to
	 * destroy the enemies
	 */
	public class Turret extends Entity{
		/* Pictures */
		[Embed(source = "../../Img/PhaseState/metralhadora_lvl1.png")]
		private var turret1BMP_lvl1 : Class; 
		[Embed(source = "../../Img/PhaseState/metralhadora_lvl2.png")]
		private var turret1BMP_lvl2 : Class; 
		[Embed(source = "../../Img/PhaseState/metralhadora_lvl3.png")]
		private var turret1BMP_lvl3 : Class; 
		[Embed(source = "../../Img/PhaseState/canhao_lvl1.png")]
		private var turret2BMP_lvl1 : Class; 
		[Embed(source = "../../Img/PhaseState/canhao_lvl2.png")]
		private var turret2BMP_lvl2 : Class; 
		[Embed(source = "../../Img/PhaseState/canhao_lvl3.png")]
		private var turret2BMP_lvl3 : Class; 
		private var turretImg : Bitmap;
		[Embed(source = "../../Img/PhaseState/baseTurret.png")]
		private var baseTurretBMP : Class; 
		private var baseTurretImg : Bitmap;
		
		//Size of the turrets
		private const TURRET1_WIDTH : int = 77;
		private const TURRET1_HEIGHT : int = 59;
		private const TURRET2_WIDTH : int = 77;
		private const TURRET2_HEIGHT : int = 45;
		
		/* The constant to define the type of the turrets */
		public static const TURRET_POINT : int = -1;
		public static const TURRET1 : int = 1;
		public static const TURRET2 : int = 2;
		public static const MAX_LEVEL : int = 3;
		
		
		/* Describes the lines of the table below (For turrets)*/
		private const POWER				: int = 0;
		private const FIRE_SPEED		: int = 1;
		private const AREA				: int = 2;
		private const REACH			    : int = 3;
		private const COST				: int = 4;
		
		/* Matrix that contains the attributes of the turrets (one matrix for each turret):
		*			Level 0 	|	Level 1 	|	Level 2 	|	Level 3 	|	
		* Power			X		|		X		|		X		|		X		|
		* FireSpeed		X		|		X		|		X		|		X		|
		* Area			X		|		X		|		X		|		X		|
		* Reach			X		|		X		|		X		|		X		|
		* Cost		X (Build)	|		X		|		X		|		X		|
		*/
		
		
		
		private var nextLevelMoney : Vector.<Number>;
		
		/* Attributes */
		private var power : Number;
		private var fireSpeed : Number;
		private var area : int;
		private var reach : int;
		
		/* Indicates wich player this turret point belongs to */
		private var player : int;
		private var playerTF : TextField;
		private var format : TextFormat;
		
		private var turret : MovieClip; //Holds the image of the turret
		
		/* The tile where the turret's in */
		private var tile : Tile;
		
		/* The enemy this turret is attacking */
		private var target : Enemy;
		
		/* The x and y coordinates of this turret tile in the
		 * tile matrix of the phase
		 */
		private var point : Point;
		
		/* Counts the frames for the next shot */
		private var frameCount : int;
		
		/** Creates a new turret.
		 * 
		 * @param type_p The type of the enemy (Enemy 1, Enemy 2, ...)
		 * @param point_p The point (x,y) this turret is in in the tile matrix
		 */
		public function Turret(type_p : int, point_p : Point) {
			type = type_p;
			createTurret();
			level = 1;
			point = point_p;
			tile = PhaseState.getTilesMatrix()[point.y][point.x];
			reach = entityV[REACH][level];
			fireSpeed = entityV[FIRE_SPEED][level]; //Shoots per second
			fireSpeed = Main.FRAME_RATE / fireSpeed;
			power = entityV[POWER][level];
			
			tile.setType(Tile.TURRET);
			tile.setTurret(this);
						
			root = new MovieClip();
			turret = new MovieClip();
			
			if(type == TURRET1){
				turretImg = new turret1BMP_lvl1();
				turretImg.width = TURRET1_WIDTH;
				turretImg.height = TURRET1_HEIGHT;
			} else if (type == TURRET2){
				turretImg = new turret2BMP_lvl1();
				turretImg.width = TURRET2_WIDTH;
				turretImg.height = TURRET2_HEIGHT;
			}
			
			baseTurretImg = new baseTurretBMP();
			baseTurretImg.width = TurretPoint.TURRET_POINT_WIDTH;
			baseTurretImg.height = TurretPoint.TURRET_POINT_HEIGHT;
			baseTurretImg.x = tile.getCenter().x - baseTurretImg.width/2;
			baseTurretImg.y = tile.getCenter().y - baseTurretImg.height/2;
			root.addChild(baseTurretImg);
			
			
			/*turretImg.width = PhaseState.tileSide;
			turretImg.height = PhaseState.tileSide;*/
			turretImg.x -= turretImg.width/2;
			turretImg.y -= turretImg.height/2;
			turret.addChild(turretImg);
			turret.x = tile.getCenter().x;
			turret.y = tile.getCenter().y;
			root.addChild(turret);
			
			playerTF = new TextField();
			playerTF.x = turret.x-turretImg.width/2-10;
			playerTF.y = turret.y-turretImg.height/2-10;
			format = new TextFormat();
			format.font = "Discognate Regular";
			format.color = 0x000000;
			playerTF.defaultTextFormat = format;
			root.addChild(playerTF);
			
			target = null;
			
			frameCount = fireSpeed; //Shoots as soon as it sees the enemy
			
		}
		
		public function sell():Number{//Returns the selling price
			destroy();
			
			//Sell it for 70% the price of buying and upgrades
			var price : Number = 0;
			for(var i:int=level; i >0; i--){
				price = price + (entityV[COST][i]*0.7);
			}
			
			return price;
		}
		
		private function destroy():void{
			root.removeChild(turret);
			turret.removeChild(turretImg);
			turretImg = null;
			turret = null;
			root = null;
			target = null;
			
			tile.setTurret(null);
			
			playerTF.text = "";
			playerTF = null;
		}
		
		public function levelUp():Boolean{
			if(level == 3){
				return false;
			}
			
			level++;
			reach = entityV[REACH][level];
			fireSpeed = entityV[FIRE_SPEED][level]; //Shoots per second
			fireSpeed = Main.FRAME_RATE / fireSpeed;
			power = entityV[POWER][level];
			
			turret.removeChild(turretImg);
			if(type == TURRET1){
				switch(level){
					case 2:
						turretImg = new turret1BMP_lvl2();
						turretImg.width = TURRET1_WIDTH;
						turretImg.height = TURRET1_HEIGHT;
					break;
					case 3:
						turretImg = new turret1BMP_lvl3();
						turretImg.width = TURRET1_WIDTH;
						turretImg.height = TURRET1_HEIGHT;
					break;
				}
			} else if (type == TURRET2){
				switch(level){
					case 2:
						turretImg = new turret2BMP_lvl2();
						turretImg.width = TURRET2_WIDTH;
						turretImg.height = TURRET2_HEIGHT;
						break;
					case 3:
						turretImg = new turret2BMP_lvl3();
						turretImg.width = TURRET2_WIDTH;
						turretImg.height = TURRET2_HEIGHT;
						break;
				}
			}
			
			turretImg.x -= turretImg.width/2;
			turretImg.y -= turretImg.height/2;
			
			turret.addChild(turretImg);
			
			return true;
		}
		
		public function enterFrame() : void{
			if (target == null){ //If there's no target, set one
				target = searchTarget();
			} else { 
				if (!target.getInGame()){
					target = null;
					return;
				} 
				turret.rotation = Util.setRotation(new Point(turret.x, turret.y), target.getCurrentPosition());
				
				shoot();
			}
		}
		
		
		/* Make this turret shoot the enemy in 'target' */
		private function shoot() : void{
			//Shoot the enemy
			frameCount++;
			if (frameCount > fireSpeed){
				if (target.takeDamage(power) <= 0) { //Shoots and check if enemy died
					PhaseState.addMoney(Enemy.MONEY_DROPPED);
					target = null;
					frameCount = fireSpeed;
				} else {
					
					//Check if the enemy has left the reach area of this turret
					var dist : int;
					dist = (Math.abs(tile.getCenter().x - target.getCurrentTile().getCenter().x) + 
						Math.abs(tile.getCenter().y - target.getCurrentTile().getCenter().y));
					if (dist > reach*PhaseState.tileSide){
						target = null;
						frameCount = fireSpeed;
					}
				}
				frameCount = 0;
			}
			
			
		}
		
		/* Look for a target */
		private function searchTarget() : Enemy{
			var i : int;
			var j : int;
			var tiles : Vector.<Vector.<Tile>> = PhaseState.getTilesMatrix();
			
			var a:int;
			var b:int;
			for(i=point.y - reach; i<=point.y+reach; i++){
				if (i <= point.y){ //Search the tiles above y
					for(j=point.x - (i - (point.y-reach)); j <= point.x + (i - (point.y-reach)); j++){
						a = i;
						a = (a<0 ? 0 : a);
						a = (a>tiles.length-1 ? tiles.length-1 : a);
						b = j;
						b = (b<0 ? 0 : b);
						b = (b>tiles[a].length-1 ? tiles[a].length-1 : b);
						if (tiles[a][b].getEnemies().length > 0){
							return tiles[a][b].getEnemies()[0];
						}
					}
				} else { //Search the tiles below y
					for(j=point.x - Math.abs(i - (point.y + reach)); j<= point.x + Math.abs(i - (point.y + reach));j++){
						a = i;
						a = (a<0 ? 0 : a);
						a = (a>tiles.length-1 ? tiles.length-1 : a);
						b = j;
						b = (b<0 ? 0 : b);
						b = (b>tiles[a].length-1 ? tiles[a].length-1 : b);
						if (tiles[a][b].getEnemies().length > 0){
							return tiles[a][b].getEnemies()[0];
						}
					}
				}
			}
			
			
			return null;
		}
		
		/* Creates the matrix 'entityV' that contains the attributes of each turret
		* based on it's level
		*/
		private function createTurret() : void{ 
			entityV = new Vector.<Vector.<Number>>(5)
			for (var i : int = 0; i < 5; i++) { //Number of attributes (lines in the matrix above)
				entityV[i] = new Vector.<Number>(4); //Number of levels
			}
			
			switch (type){
				case TURRET1:
					entityV[POWER][0] = -1; entityV[POWER][1] = 3; entityV[POWER][2] = 3; entityV[POWER][3] = 4; 
					entityV[FIRE_SPEED][0] = -1; entityV[FIRE_SPEED][1] = 1; entityV[FIRE_SPEED][2] = 2; entityV[FIRE_SPEED][3] = 2.5; 
					entityV[AREA][0] = -1; entityV[AREA][1] = -1; entityV[AREA][2] = -1; entityV[AREA][3] = -1; 
					entityV[REACH][0] = -1; entityV[REACH][1] = 2; entityV[REACH][2] = 2; entityV[REACH][3] = 3; 
					entityV[COST][0] = -1; entityV[COST][1] = 250; entityV[COST][2] = 150; entityV[COST][3] = 400; 
					
				break;
				
				case TURRET2:
					entityV[POWER][0] = -1; entityV[POWER][1] = 5; entityV[POWER][2] = 5; entityV[POWER][3] = 8; 
					entityV[FIRE_SPEED][0] = -1; entityV[FIRE_SPEED][1] = 1; entityV[FIRE_SPEED][2] = 1; entityV[FIRE_SPEED][3] = 1.5; 
					entityV[AREA][0] = -1; entityV[AREA][1] = -1; entityV[AREA][2] = -1; entityV[AREA][3] = -1; 
					entityV[REACH][0] = -1; entityV[REACH][1] = 1; entityV[REACH][2] = 2; entityV[REACH][3] = 2; 
					entityV[COST][0] = -1; entityV[COST][1] = 300; entityV[COST][2] = 300; entityV[COST][3] = 500; 
				break;
			}
		}
		
		public function getPlayer() : int{
			return player;
		}
		public function getPoint() : Point{
			return point;
		}
		public function setPlayer(player_p : int) : void{
			player = player_p;
			playerTF.text = player.toString();
		}
		public function getType():int{
			return this.type;
		}
		
		/** Get the cost to update the tower to level 'lvl'.
		 * 
		 * @param lvl The level to check the cost.
		 * @return The cost to update to that level (or to build).
		 */
		public function getCost(lvl : int) : int{
			return entityV[COST][lvl];
		}
	
	}
}